import java.util.Random;
import java.util.Scanner;


public class Node {
	private int _value;
	private Node _leftChild;
	private Node _rightChild;
	private Node _fatherNode;
	public static Node Root;
	
	public int getValue()
	{
		return this._value;
	}
	private void setValue(int value)
	{
		this._value = value;
	}
	
	public Node getLeftChild()
	{
		return this._leftChild;
	}
	public void setLeftChild(Node child)
	{
		this._leftChild = child;
	}
	
	public Node getFatherNode()
	{
		return this._fatherNode;
	}
	public void setFatherNode(Node fatherNode)
	{
		this._fatherNode = fatherNode;
	}
	
	public Node getRightChild()
	{
		return this._rightChild;
	}
	public void setRightChild(Node child)
	{
		this._rightChild = child;
	}
	
	public static void main(String argv[])
	{
		Random random = new Random(0);
		Scanner scan = new Scanner(System.in);
		int n = scan.nextInt();
		int m = scan.nextInt();
		
		if (m > 1)
		{
			int sumDepth = 0;
			for (int j = 0; j < m; j++)
			{
				Node.BuildTree(n, m, random);
				sumDepth += Node.Root.MaxDepth();
				Node.Root = null;
			}
			System.out.println(String.format("%.3f", (double)sumDepth / (double)m));
		}
		else if (m == 1)
		{
			Node.BuildTree(n, m, random);
			Node.Root.InOrder(Node.Root);
			System.out.println(String.format("%.2f", (double)Node.Root.MaxDepth()));
		}
	}
	
	public static void BuildTree(int n, int m, Random random)
	{
		int a[] = new int[n];

		for(int i=0;i<n;i++)
			a[i] = i;
		
		// Erzeuge eine zufällige Permutation des Eingabefeldes.
		// Jede Permutation hat die gleiche Wahrscheinlichkeit.
		for(int i=n-1;i>0;i--) {
			int r = (int) Math.floor((i+1)*random.nextDouble());
			Swap(a,r,i);
		}
		
		Node node = new Node(a[0], null);
		for(int g = 1; g < n; g++)
		{
			node.Insert(a[g]);
		}
	}
	
	static void Swap(int a[],int i,int j) {
		int tmp = a[i];
		a[i] = a[j];
		a[j] = tmp;
	}
	
	public Node(int value, Node root)
	{
		this.setValue(value);
		if (Node.Root == null) 
			Node.Root = this;
	}
	
	public int MaxDepth()
	{
		return MaxRecDepth(Node.Root, 1);
	}
	
	private int MaxRecDepth(Node node, int maxDepth)
	{	
		if (node == null) 
			return 0;
	    else if ( node.getLeftChild() == null && node.getRightChild() == null) 
	    	return maxDepth;
	    else 
	    {
	    	int leftMax = MaxRecDepth(node.getLeftChild(), maxDepth+ 1);
	    	int rightMax =  MaxRecDepth(node.getRightChild(), maxDepth+ 1);
	    	if (leftMax > rightMax)
	    		return leftMax;
	    	else
	    		return rightMax;
	    }
	}
	
	public void InOrder(Node node)
	{
		if (node == null) return;
		
		InOrder(node.getLeftChild());
		System.out.println(node.getValue());
		InOrder(node.getRightChild());
	}
	
	public Node Insert(int k)
	{
		Node newNode = new Node(k, null);
		
		Node tempNode = Node.Root;
		Boolean end = false;
		while(!end)
		{
			if (tempNode.getValue() > k)
			{
				if (tempNode.getLeftChild() != null)
					tempNode = tempNode.getLeftChild();
				else
					end = true;
			}
			else
			{
				if (tempNode.getRightChild() != null)
					tempNode = tempNode.getRightChild();
				else
					end = true;
			}
		}
		
		newNode.setFatherNode(tempNode);
		
		if (tempNode.getValue() > k)
			tempNode.setLeftChild(newNode);
		else
			tempNode.setRightChild(newNode);
		
		return newNode;
	}
}
